Skip to content

feat(installation): un poste neuf sort utilisable, et le bouton redémarrer redémarre - #54

Merged
lostmind84 merged 3 commits into
mainfrom
feat/installation-qui-sort-un-poste-utilisable
Aug 10, 2026
Merged

feat(installation): un poste neuf sort utilisable, et le bouton redémarrer redémarre#54
lostmind84 merged 3 commits into
mainfrom
feat/installation-qui-sort-un-poste-utilisable

Conversation

@lostmind84

Copy link
Copy Markdown
Owner

Quatre défauts trouvés en installant un poste de production, dont deux le rendaient inutilisable. Aucun n'était visible sans installer pour de vrai.

L'application est désormais en production : recette passée en magasin, deux semaines d'exploitation réelle tenues. Le lot L9 est clos.

1. Le bouton « Redémarrer le poste » laissait le poste éteint

setRecovery n'appelait que SetRecoveryActions, jamais SetRecoveryActionsOnNonCrashFailures. Windows met ce drapeau à FALSE par défaut, et faux veut dire « n'appliquer les reprises que si le service s'arrête sans signaler SERVICE_STOPPED ». Or l'arrêt ordonné de §13.4 se termine proprement et le signale : le SCM voyait un arrêt normal et n'appliquait aucune des trois reprises de §15.2.

La prémisse fausse était écrite à cinq endroits, dont ADR-055 lui-même et un banc vert intitulé « THE CODE IS THE MECHANISM » — le pire état possible. Tous corrigés ; l'ADR porte un amendement daté plutôt qu'une réécriture.

setRecovery prend désormais une interface de deux méthodes, parce qu'un banc qui ne lirait que le plan resterait vert si quelqu'un retirait le second appel — c'est exactement le défaut qui avait été livré. Vérifié en le cassant.

2. Une adresse d'écoute vide verrouillait toute l'administration

Export remet le bloc réseau à zéro et la cible release exige un export : le fichier livré porte littéralement "listen": "", donc le poste refusait sa propre configuration de livraison. PUT /admin/api/config valide le document entier, si bien qu'une seule faute portant sur un champ qu'aucun écran n'éditait empêchait le moindre enregistrement, sur toutes les pages.

Config.UnmarshalJSON ramène une adresse vide à celle du profil neutre, comme il le fait déjà pour update.repository et ui.min_products_for_chip.

L'ordre de livraison était contraint et il a été tenu : la garde d'import d'abord, le rattrapage du décodeur ensuite. Dans l'autre sens, un défaut bloquant serait devenu silencieux — le 422 était le seul garde-fou empêchant un export importé de déplacer l'écouteur d'un poste de 0.0.0.0:8085 vers la boucle locale.

La page Poste gagne enfin les champs network.listen et admin_on_lan : la mécanique de déplacement à chaud était livrée depuis toujours, seul le champ manquait — et §14.4 ne le listait pas, c'est de là que venait l'oubli.

3. Le plancher du mot de passe d'administration passe à quatre

Le chiffre existait en six exemplaires que rien ne reliait ; il est ramené à une autorité, web.MinPasswordLength, les copies qu'un autre langage impose étant liées à elle par un banc qui lit le fichier source.

Un vrai défaut, indépendant de la valeur, a été trouvé au passage : la route HTTP comptait des octets là où la ligne de commande comptait des runes — « é » vaut un caractère au clavier et deux sur le fil. Les quatre portes comptent maintenant des points de code.

4. L'installation demande ce qu'elle seule peut savoir (ADR-060)

Mot de passe d'administration, numéro et nom du poste ; la balance sort déclarée absente, faute d'en avoir une de branchée. Nouvelle action openscale config station. Aucune option de config ne prend de secret.

Fautes d'un poste neuf
Avant 4 — dont une sans aucun champ à l'écran
Après le repli de network.listen 3
Après les questions de l'installeur 1catalog.options.url, éditable à l'écran

L'empreinte va de 6c06605a à 79ba8bfc tant que la balance est déclarée absente, puis revient à 6c06605a dès qu'elle est redéclarée — mesuré dans les deux sens, et dit sur la fiche, dans le message de fin et dans INSTALLATION.md, parce que §15.5 fait comparer les quatre empreintes à l'œil.

Une relecture adverse a rattrapé ce qui aurait annulé le bénéfice : --no-scale vide scale.type, or aucun geste de l'écran ne le remettait. La détection servait pourtant déjà le driver reconnu, et detect.go l'écrivait dans son propre commentaire depuis toujours (« what goes into the form is the driver that recognised what came out of the cable »). L'écran le jetait. Un bouton « Utiliser cette balance » écrit présence, protocole et port d'un seul geste.

Les deux installeurs marchent désormais en couple

install.sh porte les six mêmes options, les mêmes questions, le même plancher, la même fiche et le même message de fin. La règle n'est pas gardée par la bonne volonté : deploy/parity_test.go lit le param() de l'un et le case de l'autre et compare dans les deux sens. Une exception est permise, jamais muette — motivée dans le banc et dans le script qui n'a pas l'option, et une raison de moins de 60 caractères fait rougir.

Deux pièges mesurés plutôt que devinés :

  • sous dash, la longueur de chaîne du shell compte des octets quelle que soit la locale : un plancher de quatre appliqué ainsi aurait accepté « éàç » — 3 caractères, 6 octets — que le binaire refuse ;
  • /proc/<pid>/cmdline est lisible par tous les comptes quand /proc/<pid>/environ ne l'est que du propriétaire : le secret descend par l'environnement, effacé avant le premier processus fils.

Vérification

go build · go test ./... (deux passes : avec cgo et -race, puis sans) 3 141 verts, 12 écartés, 0 échec sur 35 paquets
go vet · gofmt muets
npm test · svelte-check 1 021 tests sur 38 fichiers · 0 erreur
Scripts PowerShell les 6 parsent sous 5.1 et 7
Scripts POSIX les 4 passent sous le vrai dash d'une Debian

Ce qui n'est PAS fait, et n'est pas à croire fait

  • Aucun poste réel n'a été installé avec ce binaire ; la recette de redémarrage reste à éprouver sur machine.
  • sc qfailureflag n'a pas été relevé sur le poste de production : le diagnostic tient sur le source et la sémantique Windows, pas sur une mesure terrain.
  • doctor ne contrôle pas le drapeau de reprise — ce défaut resterait invisible sans matériel. Le contrôle qui l'aurait attrapé n'est pas écrit.
  • install.sh n'a jamais été lancé en entier : rien de ce qui touche apt-get, useradd, udev, polkit ni systemctl n'est exercé.
  • Les deux bootstraps ne sont pas à parité sur leurs options propres (--force, --force-install) : divergence de structure, bootstrap.sh déléguant à update.sh là où bootstrap.ps1 lance toujours install.ps1. Jugé non bloquant par le propriétaire du produit — ces options gouvernent le chemin de téléchargement, pas ce qu'un poste devient. Le banc déclare son périmètre au lieu de prétendre le couvrir.
  • Les postes déjà installés ne sont pas réparés par ce lot, par décision de périmètre : TROUBLESHOOTING.md dit sans détour qu'une mise à jour ne répare pas ce défaut, le réglage fautif vivant dans Windows et non dans le binaire.

…arrer redémarre

Quatre défauts trouvés en installant un poste de production, dont deux le rendaient
inutilisable. Aucun n'était visible sans installer pour de vrai.

1. LE BOUTON « REDÉMARRER LE POSTE » LAISSAIT LE POSTE ÉTEINT.

setRecovery n'appelait que SetRecoveryActions, jamais
SetRecoveryActionsOnNonCrashFailures. Windows met ce drapeau à faux par défaut, et faux
veut dire « n'appliquer les reprises que si le service s'arrête SANS signaler
SERVICE_STOPPED ». Or l'arrêt ordonné de §13.4 se termine proprement et le signale : le
SCM voyait un arrêt normal et n'appliquait aucune des trois reprises de §15.2.

La prémisse fausse était écrite à cinq endroits, dont ADR-055 lui-même et un banc VERT
intitulé « THE CODE IS THE MECHANISM ». Tous corrigés ; l'ADR porte un amendement daté
plutôt qu'une réécriture. setRecovery prend désormais une interface de deux méthodes,
parce qu'un banc qui ne lirait que le plan resterait vert si quelqu'un retirait le second
appel — c'est exactement le défaut qui avait été livré.

Les postes déjà installés ne sont pas réparés par ce lot : décision de périmètre du
propriétaire du produit. TROUBLESHOOTING.md dit sans détour qu'une mise à jour ne répare
pas ce défaut, le réglage fautif vivant dans Windows et non dans le binaire.

2. UNE ADRESSE D'ÉCOUTE VIDE VERROUILLAIT TOUTE L'ADMINISTRATION.

Export remet le bloc réseau à zéro et la cible release exige un export : le fichier livré
porte littéralement "listen": "", donc le poste refusait sa propre configuration de
livraison. PUT /admin/api/config valide le document ENTIER, si bien qu'une seule faute
portant sur un champ qu'aucun écran n'éditait empêchait le moindre enregistrement, sur
toutes les pages.

Config.UnmarshalJSON ramène une adresse vide à celle du profil neutre, comme il le fait
déjà pour update.repository et ui.min_products_for_chip. L'ordre de livraison était
contraint et il a été tenu : la garde d'import d'abord, le rattrapage du décodeur ensuite.
Dans l'autre sens, un défaut bloquant serait devenu silencieux — le 422 était le seul
garde-fou empêchant un export importé de déplacer l'écouteur d'un poste de 0.0.0.0:8085
vers la boucle locale.

La page Poste gagne enfin les champs network.listen et admin_on_lan : la mécanique de
déplacement à chaud était livrée depuis toujours, seul le champ manquait — et §14.4 ne le
listait pas, c'est de là que venait l'oubli.

3. LE PLANCHER DU MOT DE PASSE D'ADMINISTRATION PASSE À QUATRE.

Demande du propriétaire du produit. Le chiffre existait en six exemplaires que rien ne
reliait ; il est ramené à une autorité, web.MinPasswordLength, les copies qu'un autre
langage impose étant liées à elle par un banc qui LIT le fichier source.

Un vrai défaut, indépendant de la valeur, a été trouvé au passage : la route HTTP comptait
des octets là où la ligne de commande comptait des runes. Les quatre portes comptent
maintenant des points de code, PowerShell compris.

4. L'INSTALLATION DEMANDE CE QU'ELLE SEULE PEUT SAVOIR (ADR-060).

Mot de passe d'administration, numéro et nom du poste, et la balance sort déclarée absente
faute d'en avoir une de branchée. Nouvelle action « openscale config station ». Aucune
option de config ne prend de secret : le mot de passe passe par l'entrée standard, un
argument se lisant dans la liste des processus.

Un poste neuf passe de 4 fautes à 1. L'empreinte va de 6c06605a à 79ba8bfc tant que la
balance est déclarée absente, puis revient à 6c06605a dès qu'elle est redéclarée — mesuré
dans les deux sens, et dit sur la fiche, dans le message de fin et dans INSTALLATION.md,
parce que §15.5 fait comparer les quatre empreintes à l'œil.

Une relecture adverse a rattrapé ce qui aurait annulé le bénéfice : --no-scale vide
scale.type, or aucun geste de l'écran ne le remettait. La détection servait pourtant déjà
le driver reconnu, et detect.go l'écrivait dans son propre commentaire depuis toujours.
Un bouton « Utiliser cette balance » écrit présence, protocole et port d'un seul geste.

LES DEUX INSTALLEURS MARCHENT DÉSORMAIS EN COUPLE.

install.sh porte les six mêmes options, les mêmes questions, le même plancher, la même
fiche et le même message de fin. La règle n'est pas gardée par la bonne volonté :
deploy/parity_test.go lit le param() de l'un et le case de l'autre et compare dans les
deux sens. Une exception est permise, jamais muette — motivée dans le banc ET dans le
script qui n'a pas l'option.

Deux pièges mesurés plutôt que devinés. Sous dash, la longueur de chaîne du shell compte
des OCTETS quelle que soit la locale : un plancher de quatre appliqué ainsi aurait accepté
« éàç », que le binaire refuse. Et /proc/<pid>/cmdline est lisible par tous les comptes
quand /proc/<pid>/environ ne l'est que du propriétaire : le secret descend par
l'environnement, effacé avant le premier processus fils.

STATUT : l'application est EN PRODUCTION. Recette passée en magasin, deux semaines
d'exploitation réelle tenues. Le lot L9 est clos.

Vérification : go build, go test en deux passes (avec cgo et -race, puis sans), 3 141
tests verts sur 35 paquets, go vet et gofmt muets, 1 021 tests web, svelte-check à 0
erreur, les six scripts PowerShell parsent sous 5.1 et 7, les quatre scripts POSIX passent
sous le vrai dash d'une Debian.

Ce qui n'est PAS fait, et n'est pas à croire fait : aucun poste réel n'a été installé avec
ce binaire ; sc qfailureflag n'a pas été relevé sur le poste de production ; doctor ne
contrôle pas le drapeau de reprise, donc ce défaut resterait invisible sans matériel ;
install.sh n'a jamais été lancé en entier, donc rien de ce qui touche apt-get, useradd,
udev, polkit ni systemctl n'est éprouvé ; les deux bootstraps ne sont pas à parité sur
leurs options propres, écart jugé non bloquant par le propriétaire du produit.
…nner Linux

La CI a refusé le lot précédent, et elle avait raison. Sur ubuntu-latest, pwsh EST
installé : les trois bancs ajoutés le 10/08/2026 démarraient donc, puis mouraient en
dot-sourçant common.ps1, dont la toute première ligne dérive ses chemins de
%ProgramFiles% — vide hors Windows. « Join-Path: Cannot bind argument to parameter
'Path' because it is null », une panne qui ne dit rien de ce que le banc voulait prouver
et tout de la machine qui l'a joué.

LE PIÈGE ÉTAIT DÉJÀ DOCUMENTÉ, et c'est ce qui rend l'incident intéressant :
TestTheBackupAndTheRestoreWorkOnAThrowawayDirectory portait ce raisonnement depuis
toujours — dans un commentaire, à lui seul. Trois bancs neufs sont passés à côté sans le
voir. Le raisonnement déménage donc sur requireWindowsToRunCommonPs1, pour que le suivant
ait à passer devant un NOM plutôt que devant le commentaire de quelqu'un d'autre.

La moitié STATIQUE de TestTheFourthDoorCountsCodePointsLikeTheOtherThree — le refus d'un
plancher comparé à un .Length — continue de tourner partout : elle lit du texte. Seule la
moitié MESURÉE est gardée.

ET LE TROU QUE LA GARDE OUVRAIT EST FERMÉ AUSSI. Les jobs ubuntu jouent le paquet entier
et sautent désormais ces trois bancs ; le job windows-latest, lui, ne joue qu'un
sous-ensemble NOMMÉ, pour ne pas jouer le paquet deux fois. Mis bout à bout, un banc
pouvait être ajouté, gardé, et ne tourner NULLE PART : vert sur tous les jobs, ne prouvant
rien. C'est pire qu'un test manquant — un banc sauté se lit comme couvert.

TestEveryWindowsOnlyBenchIsRunByTheWindowsJob le refuse : il relève les bancs qui appellent
la garde, LIT le -run du job Windows là où il vit plutôt que d'en tenir une seconde copie,
et exige que chacun y soit sélectionné. Vérifié en le cassant : un nom retiré du filtre, le
banc rougit en nommant le banc orphelin et le fichier à corriger.

Vérification : go build, go test en deux passes (avec cgo et -race, puis sans), go vet et
gofmt muets. La preuve qui manque est celle que seule la CI peut donner — que les trois
bancs sautent proprement sur ubuntu et s'exécutent sur windows-latest.
…t le binaire qui la mange

Premier passage de ces bancs sur un VRAI Windows, et il a trouvé quelque chose qu'aucune
machine de développement n'avait reproduit : sous powershell.exe 5.1, le tube vers un
processus natif livre EF BB BF quoi qu'on règle. La marque est présente jusque dans la
mesure de RÉFÉRENCE en us-ascii que ce banc journalise — elle ne vient donc d'aucun des
deux réglages de Set-NativeOutputEncoding, qui demandent bien tous les deux
UTF8Encoding($false). pwsh 7 ne le fait pas.

Or 5.1 est le seul shell qu'ait le poste réel : common.ps1 le dit dans son propre en-tête.

CE QUI COMPTE EST LE CONTRAT, et le contrat est ce que le binaire HACHE : le mot de passe
qui a été tapé. Exiger un tube immaculé exigeait plus que ça, sur un shell dont nous ne
gouvernons pas le comportement. Le banc admet donc une marque de tête — que readSecretLine
retire déjà, et que TestAByteOrderMarkIsNotPartOfThePassword tient — et continue d'exiger
ce qui murerait vraiment un poste : aucun accent transformé en « ? ».

DEUX COMMENTAIRES DEVENAIENT FAUX ET SONT CORRIGÉS. common.ps1 affirmait que son réglage
« fait que la question ne se pose pas » : la mesure dit le contraire, et la fonction sert
en réalité l'ACCENT, pas la marque. Et le retrait du U+FEFF dans readSecretLine cesse
d'être présenté comme un bonus : il est PORTEUR, sur le seul shell qui soit livré. Le
supprimer murerait tout poste installé depuis une console 5.1 avec un mot de passe
accentué.

C'est la deuxième chose que ce job Windows trouve en deux commits, après n'avoir jamais
joué ces bancs : il valait la peine d'y brancher les trois.
@lostmind84
lostmind84 merged commit 1f03ec6 into main Aug 10, 2026
8 checks passed
@lostmind84
lostmind84 deleted the feat/installation-qui-sort-un-poste-utilisable branch August 10, 2026 14:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant